import React from 'react';
import {
  Form, Button, Select, Divider,
} from 'antd';
import { keys, omit, has } from 'lodash/fp';
import ParamFormItem from 'components/ParamFormItem';

const { Option } = Select;

class TaskForm extends React.Component {
  constructor(props) {
    super(props);
    this.inputRef = null;
    this.modeler = null;
    this.state = {
      apis: [],
      startInterface: null,
    };
  }

  componentDidMount() {
    const { taskObj } = this.props;
    if (taskObj) {
      this.setSelectedApis(taskObj.service);
    }
  }

  handleSubmit = async (e) => {
    e.preventDefault();
    const {
      form: { getFieldsValue, validateFieldsAndScroll },
      services,
      updateBPMN,
      addTaskOutput,
      closeModal,
      taskId,
      setTaskState,
    } = this.props;

    try {
      await validateFieldsAndScroll();
      const {
        service, startInterface, detectInterface, params, // params should contain args & input
      } = getFieldsValue();
      const serviceObj = services[service];
      const startInterfaceObj = serviceObj.apis[startInterface];
      const detectInterfaceObj = serviceObj.apis[detectInterface];
      // normalize params.input fomat ([] -> string)
      if (params && params.input) {
        keys(params.input).forEach((key) => {
          params.input[key] = params.input[key].join('.');
        });
      }
      updateBPMN(
        taskId,
        params,
        serviceObj.name,
        startInterfaceObj.description,
        startInterfaceObj.path,
        detectInterfaceObj.path,
      );

      setTaskState(taskId, getFieldsValue());
      // TODO: use correct response (with status code 200) instead of [0]
      // TODO: add datatype in output
      try {
        addTaskOutput(
          taskId,
          keys(detectInterfaceObj.responses[0].schema.properties.data.properties),
        );
      } catch (err) {
        // addTaskOutput([]);
      }

      closeModal();
    } catch (err) {
      console.error(err);
    }
  }

  setSelectedApis(index) {
    const { services, form: { getFieldsValue } } = this.props;
    const { startInterface } = getFieldsValue();
    const { apis } = services[index];
    if (startInterface !== undefined && apis.length > startInterface + 1) {
      this.setState({
        apis,
        startInterface: apis[startInterface],
      });
    } else {
      this.setState({
        apis,
      });
    }
  }

  setSelectedStartInterface(index) {
    const { apis } = this.state;
    this.setState({
      startInterface: apis[index],
    });
  }

  findParamInTaskObj = (paramName, taskObj) => {
    if (taskObj) {
      if (has(`params.args.${paramName}`, taskObj)) { // in args
        return {
          in: 'args',
          value: taskObj.params.args[paramName],
        };
      } if (has(`params.input.${paramName}`, taskObj)) {
        return {
          in: 'input',
          value: taskObj.params.input[paramName],
        };
      }
    }
    return null;
  }

  render() {
    const {
      services, taskId, form: { getFieldDecorator }, taskOutput, taskObj,
    } = this.props;
    const { findParamInTaskObj } = this;
    const availableOutput = omit([taskId], taskOutput); // omit the id of current task
    const { apis, startInterface } = this.state;
    const inputItems = startInterface
      ? startInterface.params.map((param) => (
        <ParamFormItem
          key={param.name}
          param={{ ...param, label: param.name }}
          getFieldDecorator={getFieldDecorator}
          taskOutput={availableOutput}
          defaults={findParamInTaskObj(param.name, taskObj)}
        />
      )) : [];
    return (
      <Form
        labelCol={{ xs: { span: 24 }, sm: { span: 6 } }}
        wrapperCol={{
          xs: { span: 24 },
          sm: { span: 18 },
        }}
        onSubmit={this.handleSubmit}
      >
        <Divider orientation="left">流程接口设置</Divider>
        <Form.Item label="选择微服务">
          {getFieldDecorator('service', {
            rules: [
              {
                required: true,
                message: '请选择微服务!',
              },
            ],
            initialValue: taskObj ? taskObj.service : null,
          })(
            <Select onChange={(index) => { this.setSelectedApis(index); }}>
              {
                services.map((item, index) => (
                  <Option key={item.id} value={index}>{`${item.name} (${item.description})`}</Option>
                ))
              }
            </Select>,
          )}
        </Form.Item>
        <Form.Item label="任务启动接口">
          {getFieldDecorator('startInterface', {
            rules: [
              {
                required: true,
                message: '请选择任务启动接口!',
              },
            ],
            initialValue: taskObj ? taskObj.startInterface : null,
          })(
            <Select onChange={(index) => { this.setSelectedStartInterface(index); }}>
              {
                apis.map((item, index) => (
                  <Option key={item.name} value={index}>{item.description}</Option>
                ))
              }
            </Select>,
          )}
        </Form.Item>
        <Form.Item label="状态查询接口">
          {getFieldDecorator('detectInterface', {
            rules: [
              {
                required: true,
                message: '请选择状态查询接口!',
              },
            ],
            initialValue: taskObj ? taskObj.detectInterface : null,
          })(
            <Select>
              {
                apis.map((item, index) => (
                  <Option key={item.name} value={index}>{item.description}</Option>
                ))
              }
            </Select>,
          )}
        </Form.Item>
        {
          inputItems.length > 0 ? <Divider orientation="left">任务输入参数</Divider> : null
        }
        {inputItems}
        {/**
          * TODO: add specifying task output (maybe?)
          * <Divider orientation="left">任务可用输出</Divider>
          */}
        <Button type="primary" htmlType="submit" style={{ width: '100%' }}>
          确定
        </Button>
      </Form>
    );
  }
}

export default Form.create({})(TaskForm);
